package com.jerry.boot.business.auth;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.jerry.boot.business.auth.pojo.AuthDto;
import com.jerry.boot.business.user.User;
import com.jerry.boot.business.user.UserService;
import com.jerry.boot.core.JConstant;
import com.jerry.boot.core.base.ApiException;
import com.jerry.boot.core.base.UnauthorizedException;
import com.jerry.boot.core.web.ServletContextHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;

@Component
@Slf4j
public class AuthTokenValidator implements AuthValidator {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private UserService userService;

    @Override
    public void validate(HttpServletRequest request) throws ApiException {
        //仅拦截Ajax请求，
        if (ServletContextHelper.isAjaxRequest(request)) {
            AuthDto authDto = (AuthDto) request.getSession().getAttribute(JConstant.AUTH_USER_KEY);
            //session中的authDto未超时，说明用户处于登录状态
            if (authDto != null) {
                return;
            }

            String accessToken = ServletUtil.getHeader(request, JConstant.ACCESS_TOKEN, StandardCharsets.UTF_8);
            //请求头中未携带accessToken
            if (StrUtil.isBlank(accessToken)) {
                throw new UnauthorizedException();
            }

            String username = stringRedisTemplate.opsForValue().get("access:token:" + accessToken);
            //accessToken未在redis中存在
            if (StrUtil.isBlank(username)) {
                throw new UnauthorizedException();
            }

            User user = userService.getUserByUsername(username);
            //accessToken映射的username在数据库中查不到
            if (user == null) {
                throw new UnauthorizedException();
            }
            //重新组装authDto放入session中，此处不再生成refreshToken。token超时后请使用登录时生成的refreshToken请求生成新的accessToken
            authDto = new AuthDto();
            authDto.setUsername(user.getUsername());
            authDto.setAccessToken(accessToken);
            request.getSession().setAttribute(JConstant.AUTH_USER_KEY, authDto);
        }
    }
}
